struts1 与 struts2 总结。

struts1 所学版本:1.3.8
struts2 所学版本:2.5.10.1

补充 tomcat 知识

默认虚拟主机

我们知道,server.xml 中可以配置多个 host,在 engine 标签中可以修改 default 属性,即浏览器直接访问 ip 地址时,访问的哪一个虚拟主机。

默认 web application

一个虚拟主机中可以部署多个 web 应用。当浏览器指定了虚拟主机(或者 tomcat 知道了需要访问哪一个主机),没有指定 web 应用时,tomcat 会看 server.xml 中 host 标签,或者 $CATALINA_HOME/conf /Catalina/localhost 目录下有没有 context 标签的 path 属性设置为空,有的话,访问这个 web 应用。没有的话,访问 Tomcat/webapps/ROOT 应用(新下载的 tomcat 就是这种方式)。再没有的话,就报错。

默认主页

一个 web 应用中可以有很多个页面,当浏览器指定了 web 应用(或者 tomcat 知道了需要访问哪一个 web 应用),没有指定页面时,会有两种情况,自己不太确定会发生哪一种。凭感觉第二种更可能。

  1. tomcat 会访问 web.xml 中匹配了所有路径的 servlet。若没有这个 servlet,或者 这个 servlet 没有指定返回的页面时,就会访问欢迎页面。欢迎页面说明见下面。
  2. tomcat 会直接指定为欢迎页面,页面确定后,就是正常的处理流程了。如果没有欢迎页面,则访问 web.xml 中匹配了所有路径的 servlet。

经过自己测试,发现是第二种。

web.xml 中欢迎页面

<welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>index1.jsp</welcome-file>
</welcome-file-list>

上面的例子指定了2个欢迎页面,显示时按顺序从第一个找起,如果第一个存在,就显示第一个,后面的不起作用。如果第一个不存在,就找第二个,以此类推。

关于欢迎页面:访问一个网站时,默认看到的第一个页面就叫欢迎页,一般情况下是由首页来充当欢迎页的。一般情况下,我们会在web.xml中指定欢迎页。但web.xml并不是一个Web的必要文件,没有web.xml,网站仍然是可以正常工作的。只不过网站的功能复杂起来后,web.xml的确有非常大用处,所以,默认创建的动态web工程在WEB-INF文件夹下面都有一个web.xml文件。

对于tomcat来说,当你只指定一个web的根名,没有指定具体页面,去访问时一个web时,如果web.xml文件中配置了欢迎页,那么就返回指定的那个页面作为欢迎页,而在文中没有web.xml文件,或虽然有web.xml,但web.xml也没指定欢迎页的情况下,它默认先查找index.html文件,如果找到了,就把index.html作为欢迎页还回给浏览器。如果没找到index.html,tomcat就去找index.jsp。找到index.jsp就把它作为欢迎页面返回。而如果index.html和index.jsp都没找到,又没有用web.xml文件指定欢迎页面,那此时tomcat就不知道该返回哪个文件了,它就显示The requested resource (/XXX) is not available(我就出现过这个问题)的页面。其中XXX表示web的根名。但如果你指定了具体页面,是可以正常访问的。

因为 tomcat/conf/web.xml 中有如下内容:

<welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
</welcome-file-list>

参考网页:http://www.cnblogs.com/hxsyl/p/3435412.html

results 标签

default results type

<result-types>
   <result-type name="dispatcher" default="true"
                class="org.apache.struts2.dispatcher.ServletDispatcherResult" />
</result-types>

If a type attribute is not specified, the framework will use the default dispatcher type, which forwards to another web resource. If the resource is a JavaServer Page, then the container will render it, using its JSP engine.

Result element without defaults

<result name="success" type="dispatcher">
    <param name="location">/ThankYou.jsp</param>
</result>

或者

<result>/ThankYou.jsp</result>

Tips:results 标签必须设置三个值:name,type,location。name 默认为“success”,type 默认为“dispatcher”。

struts2

struts.xml

package 标签作用:用来解决 package 中 action 重名的情况。

package提供了将多个Action组织为一个模块的方式。
package的名字必须是唯一的 package可以扩展,当一个package扩展自另一个package时该package会在本身配置的基础上加入扩展的package
的配置,父package必须在子package前配置。

abstract:设置package的属性为抽象的,抽象的package不能定义action。

官网标签说明:https://struts.apache.org/docs/package-configuration.html

namespace

namespace决定了action的访问路径,默认为””,可以接收所有路径的action。

namespace可以写为/,或者/xxx,或者/xxx/yyy,对应的action访问路径为/index.action,
/xxx/index.action,或者/xxx/yyy/index.action.

namespace 最好也用模块来进行命名。

namespace 默认值为空字符串(“”)时,处理其他 package 中同名 action 处理不了的请求。即没有更精确 namespace 匹配时,用这个action。

Action

具体视图的返回可以由用户自己定义的Action来决定。

具体的手段是根据返回的字符串找到对应的配置项,来决定视图的内容。

具体Action的实现可以是一个普通的java类,里面有public String execute方法即可。

或者实现Action接口。

不过最常用的是从ActionSupport继承,好处在于可以直接使用Struts2封装好的方法。

当 action 标签中不配置 class 属性时,默认为 ActionSupport 类。
action 标签中 result 子标签默认 name=“result”。

路径问题

struts2中的路径问题是根据action的路径而不是jsp路径来确定,所以尽量不要使用相对路径。

虽然可以用redirect方式解决,但redirect方式并非必要。

解决办法非常简单,统一使用绝对路径。(在jsp中用request.getContextRoot方式来拿到webapp的路径)。
或者指定basePath。

DMI

The default entry method to the handler class is defined by the Action interface.
Sometimes, developers like to create more than one entry point to an Action. A different entry point can be specified by the method attribute.

Action执行的时候并不一定要执行execute方法。

可以在配置文件中配置Action的时候用method=来指定执行哪个方法,也可以在url地址中动态指定(动态方法调用DMI)(推荐)。

前者会产生太多的action,所以不推荐使用。

action 的通配符匹配
<action name="Student*" class="com.bjsxt.struts2.action.StudentAction" method="{1}">
    <result>/Student{1}_success.jsp</result>
</action>
<action name="*_*" class="com.bjsxt.struts2.action.{1}Action" method="{2}">
    <result>/{1}_{2}_success.jsp</result>
    <!-- {0}_success.jsp -->
</action>

使用通配符,将配置量降到最低。

不过,一定要遵守”约定优于配置”的原则。

action 的属性接受参数
  1. 用 Action 的属性接受参数,通过请求的 url 传递给 action。
    例子:/actionName!methodName?attributeName=attributeValue
  2. 用 DomainModel 接受参数,也是通过请求的 url 传递给 action。
    例子:/actionName!methodName?modelName.attributeName=attributeValue
    当参数个数不匹配时,可以用 DTO 技术。(最常用)
  3. 用 ModelDriven 传输参数,不常用。action 需要实现 ModelDriven 接口,请求的 url 与第一种一样。
获得 web 元素

action 中获得 Request,Session,Application 对象

方法一:

Map request = (Map) ActionContext.getContetx().get("request");

方法二:
action 实现 RequestAware,SessionAware,ApplicationAware 接口。
通过 DI(依赖注入)、IoC(控制反转)获得 request,session,application 对象。(只用这种)

action 中获得 HttpServletRequest,HttpSession,ServletContext 对象

方法一:(基本不用)

HttpServletRequest request = ServletActionContext.getRequest();
HttpSession session = request.getSession();
ServletContext application = session.getServletContext();

方法二:

action 实现 ServletRequestAware 接口。
也是通过依赖注入获得对象。

jsp 页面中获得 web 元素

<s:property value="#request.r1"/> | <%=request.getAttribute("r1") %>

附上 struts2 架构图

struts1 与 struts2 区别

struts1

  1. 基于Servlet(ActionServlet),actionForm众多(类的爆炸),action单例(数据安全[线程安全]问题).
  2. 将所有任务的解决都集于一身.(不容易扩展和定制)
  3. action位于控制层. extends Action{…}
  4. action更struts1的action和原生servlet api(HttpServletRequest,HttpServlerResponse)绑定在一起,因此不容易测试,需要部署到web容器中进行测试.
1
2
3
4
5
6
7
8
public class RegisterAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
}
}

或者

1
2
3
4
5
6
7
8
class CustomerAction extends DispatchAction{
public ActionForward save(ActionMapping,ActionForm,Request,Response){
}
public ActionForward update(ActionMapping ActionForm Request,Response){
}
}
<action-mappings>
    <action path="/customerAction"
            name="customerForm"
            scope="request|session"
            validate="true"
            input="/xxx.jsp"
            forward="/xxx.jsp"
            type="xxxx..CustomerAction"
            parameter="method">
    </action>
</action-mappings>

访问方式:http://xxx/sss/customerAction.do?method=save,其中 method=save 表示传递了 method 参数,值为 save。

可以在 action 标签的forward 属性中设置,action产生的结果 forward 到哪一个 jsp。也可以在 action 对象返回的 ActionForward 对象中指定。

action execute 方法

数据的传递

可以把消息存放在 request 域中,jsp 文件通过 EL 表达式获取 。

request.setAttribute("message", "注册成功!!");

jsp 文件中内容:

${message}

forward 到哪一个 jsp

可以在 action返回的 ActionForward 对象中指定 forward 到哪一个 jsp:

return new ActionForward("/message.jsp");

也可以在 action 标签的forward 属性中设置 forward 到哪一个 jsp 后,

<forward name="message" path="/message.jsp"></forward>

代码中可以直接写:

return mapping.findForward("message");//会找到配置文件中 name="message" 的 forward 标签。

struts2

  1. 基于filter,没有actionform,action(原型的,独占).
  2. seperate aware:分离关注.解耦.(interceptor,拦截器).
  3. action是模型层(接受参数+pojo).
  4. action不需要和struts的action和原生servlet API(HttpServletRequest,HttpServlerResponse)耦合在一起.所以更容易测试,不需要一定要部署到web环境中进行测试.
  5. struts2是更加整洁的mvc框架(原因是采用了seperate aware技术,实现任务的拆解).



    /xxx.jsp

可以直接在配置文件中 result 标签中设置,action产生的结果 forward 到哪一个 jsp。

jsp 中可以使用 <s:property> 标签获得 value stack 中内容。

顺带也说一下不用框架,直接访问 servlet 对象情况

在 web.xml 文件中配置如下:

<servlet>
        <servlet-name>FirstServlet</servlet-name>
        <servlet-class>cn.itcast.FirstServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>FirstServlet</servlet-name>
    <url-pattern>/xxx</url-pattern>
</servlet-mapping>

tomcet 根据 url-pattern 来找到对应的 servlet-class 来相应请求。

产生的结果可以直接输出,也可以 forward 到 jsp。

request.getRequestDispatcher("/xxx.jsp").forward(request, response);
本文总阅读量次.

留言